home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / prtprev / genprint.txt < prev    next >
Text File  |  1994-04-03  |  19KB  |  539 lines

  1. How to Add Print Preview to Visual Basic Applications         [B_VBasic]
  2. ID: Q113236    CREATED: 29-MAR-1994   MODIFIED:            
  3. 2.00 3.00
  4. Windows
  5. ENDUSER | 
  6.  
  7. --------------------------------------------------------------
  8. The information in this article applies to:
  9.  
  10. - Standard and Professional Editions of Microsoft Visual Basic
  11.   Programming System for Windows, version 2.0 and 3.0
  12. --------------------------------------------------------------
  13.  
  14. SUMMARY
  15. =======
  16.  
  17. This article describes how to create printing routines that can
  18. print to the printer or to a picture box. This enables you to add
  19. print preview capabilities to your Visual Basic applications.
  20.  
  21. There are several ways that you could implement print preview in
  22. your applications. This article describes one method that is easy
  23. to do in Visual Basic and works well.
  24.  
  25. MORE INFORMATION
  26. ================
  27.  
  28. Generic Printing
  29. ----------------
  30.  
  31. It would be ideal to have a generic print routine that could print
  32. to the printer or to the screen depending on what you pass it. The
  33. Visual Basic printer object and picture box control have many of the
  34. same methods and properties. For example, both of these are valid:
  35.  
  36.    Printer.Print AString
  37.    Picture1.Print AString
  38.  
  39. It would be nice if you could pass a generic object to a subroutine
  40. and the subroutine would use the Print method off of the generic object
  41. as in this example:
  42.  
  43.    Call PrintJob(Printer)
  44.    Call PrintJob(Picture1)
  45.  
  46.    Sub PrintJob(GenericObject As Object)
  47.       GenericObject.Print AString
  48.    End Sub
  49.  
  50. Unfortunately, this is not possible. The Visual Basic Printer object
  51. is a system object, so it can't be passed as a parameter.
  52.  
  53. This leaves you with two choices in Visual Basic. You could create two
  54. routines -- one for printing to the printer and one for print preview.
  55.  However, the code would not be reusable in your future projects. The
  56. second approach is to write your own set of routines that can print to
  57. the printer or a picture box based on the value of a flag. This is the
  58. method used in the example code given below. Once you create the
  59. routines, you can re-use them in future programs.
  60.  
  61. The example creates routines that closely mimic Visual Basic's built in
  62. methods and properties. However, you could use this approach to create
  63. high-level routines that greatly simplify your printing needs.
  64.  
  65. The routines work by checking the variable PrinterFlag. PrinterFlag is
  66. True when printing is going to the printer and False when printing to
  67. the picture box.
  68.  
  69. Here's the print routine from the example. Notice how it is just a
  70. shell function that determines what to print to and then does it.
  71.  
  72.    Sub PrintPrint (PrintVar)
  73.       If PrinterFlag Then
  74.          Printer.Print PrintVar
  75.       Else
  76.          objPrint.Print PrintVar
  77.       End If
  78.    End Sub
  79.  
  80. With just a few simple routines like this, you can start to do
  81. generic printing.
  82.  
  83. Scaling
  84. -------
  85.  
  86. To accomplish print preview, the program must scale the output to the
  87. picture box to match the output on the printer.
  88.  
  89. In the example, the PrintStartDoc routine initializes the printer or
  90. picture box and sets up the scaling. The width and height of the paper
  91. are passed to the PrintStartDoc routine. These dimensions are used to
  92. determine the non-printable area of the printer object, find the ratio
  93. of the picture box to the printer, re-size the picture box, and scale
  94. the picture box. The picture box is scaled with the Scale method. After
  95. setting the scale of the picture box, graphic methods use the new
  96. coordinates. For an 8.5 x 11 inch piece of paper the picture box is
  97. scaled with this command:
  98.  
  99.    Picture1.Scale (0, 0)-(8.5, 11)
  100.  
  101. The Scale method does not scale fonts. To scale the fonts, use the
  102. ratio of the picture box height divided by the printer's height in
  103. inches. Then multiply by this ratio to determine the correct font
  104. size within the picture box. Here is the PrintFontSize routine that
  105. sets the appropriate font sizes in the example:
  106.  
  107.    Sub PrintFontSize (pSize)
  108.       If PrinterFlag Then
  109.          Printer.FontSize = pSize
  110.       Else
  111.          'Sized by ratio since Scale method does not effect FontSize
  112.          ObjPrint.FontSize = pSize * Ratio
  113.       End If
  114.    End Sub
  115.  
  116. The ratio used to calculate the font size can be applied to anything
  117. you need to scale in the picture box that is not automatically scaled
  118. by the Scale method. The ratio is also used in the PrintPicture routine
  119. to scale pictures.
  120.  
  121. Step-by-Step Example
  122. --------------------
  123.  
  124. 1. Start a new project in Visual Basic. Form1 is created by default.
  125.  
  126. 2. Add a command button (Command1), a check box (Check1), and two
  127.    picture boxes (Picture1 and Picture2) to the form.
  128.  
  129. 3. Put the following code in the command button click event:
  130.  
  131.    Sub Command1_Click ()
  132.    'Setup (Could be done at design time or in form load)
  133.    'Make printing stick
  134.    Picture1.AutoRedraw = True
  135.    'Add a palette for 256 colors
  136.    Picture1.Picture = LoadPicture("C:\VB\PASTEL.DIB")
  137.    'Setup hidden picture
  138.    Picture2.AutoRedraw = False
  139.    Picture2.ScaleMode = 3 'Pixels
  140.    Picture2.Visible = False
  141.    Picture2.AutoSize = True
  142.    Picture2.Picture = LoadPicture("C:\VB\METAFILE\BUSINESS\PRINTER.WMF")
  143.  
  144.    'This print job can go to the printer or the picture box
  145.    If Check1.Value = 0 Then PrinterFlag = True
  146.    PrintStartDoc Picture1, PrinterFlag, 8.5, 11
  147.  
  148.    'All the subs use inches
  149.    PrintBox 1, 1, 6.5, 9
  150.    PrintLine 1.1, 2, 7.4, 2
  151.    PrintPicture Picture2, 1.1, 1.1, .8, .8
  152.    PrintFilledBox 2.1, 1.2, 5.2, .7, RGB(200, 200, 200)
  153.    PrintFontName "Arial"
  154.    PrintCurrentX 2.3
  155.    PrintCurrentY 1.3
  156.    PrintFontSize 35
  157.    PrintPrint "Visual Basic Printing"
  158.    For x = 3 To 5.5 Step .2
  159.       PrintCircle x, 3.5, .75
  160.    Next
  161.    PrintFontName "Courier New"
  162.    PrintFontSize 30
  163.    PrintCurrentX 1.5
  164.    PrintCurrentY 5
  165.    PrintPrint "It is possible to do"
  166.    PrintFontSize 24
  167.    PrintCurrentX 1.5
  168.    PrintCurrentY 6.5
  169.    PrintPrint "It is possible to do print"
  170.    PrintFontSize 18
  171.    PrintCurrentX 1.5
  172.    PrintCurrentY 8
  173.    PrintPrint "It is possible to do print preview"
  174.    PrintFontSize 12
  175.    PrintCurrentX 1.5
  176.    PrintCurrentY 9.5
  177.    PrintPrint "It is possible to do print preview with good results."
  178.    PrintEndDoc
  179.    End Sub
  180.  
  181. 4. Add a new Module to the project (MODULE1.BAS).
  182.  
  183. 5. Put the following code in the basic module:
  184.  
  185.    Option Explicit
  186.  
  187.    ' The following Types, Declares, and Constants are only necessary for the
  188.  
  189.    ' PrintPicture routine
  190.    '=========================================================================
  191. =
  192.    Type BITMAPINFOHEADER_TYPE
  193.       biSize As Long
  194.       biWidth As Long
  195.       biHeight As Long
  196.       biPlanes As Integer
  197.       biBitCount As Integer
  198.       biCompression As Long
  199.       biSizeImage As Long
  200.       biXPelsPerMeter As Long
  201.       biYPelsPerMeter As Long
  202.       biClrUsed As Long
  203.       biClrImportant As Long
  204.       bmiColors As String * 1024
  205.    End Type
  206.  
  207.    Type BITMAPINFO_TYPE
  208.       BitmapInfoHeader As BITMAPINFOHEADER_TYPE
  209.       bmiColors As String * 1024
  210.    End Type
  211.  
  212.    'Each of the following declares should be entered on a single line
  213.    Declare Function GetDIBits Lib "gdi" (ByVal hDC As Integer,
  214.       ByVal hBitmap As Integer, ByVal nStartScan As Integer,
  215.       ByVal nNumScans As Integer, ByVal lpBits As Long,
  216.       BitmapInfo As BITMAPINFO_TYPE, ByVal wUsage As Integer) As Integer
  217.    Declare Function StretchDIBits Lib "gdi" (ByVal hDC As Integer,
  218.       ByVal DestX As Integer, ByVal DestY As Integer,
  219.       ByVal wDestWidth As Integer, ByVal wDestHeight As Integer,
  220.       ByVal SrcX As Integer, ByVal SrcY As Integer,
  221.       ByVal wSrcWidth As Integer, ByVal wSrcHeight As Integer,
  222.       ByVal lpBits As Long, BitsInfo As BITMAPINFO_TYPE,
  223.       ByVal wUsage As Integer, ByVal dwRop As Long) As Integer
  224.    Declare Function GlobalAlloc Lib "kernel" (ByVal wFlags As Integer,
  225.       ByVal lMem As Long) As Integer
  226.    Declare Function GlobalLock Lib "kernel" (ByVal hMem As Integer) As Long
  227.    Declare Function GlobalUnlock Lib "kernel"
  228.       (ByVal hMem As Integer) As I